# -*- coding: utf-8 -*-

from collections import OrderedDict

from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash

from sqlalchemy.dialects import mysql

from wxgame import db, login_manager
from manager.models import ts_func


class Permission:
    READ_DATA = 0x01
    UP_POINT = 0x02
    DOWN_POINT = 0x04
    CLEAN_WAGER = 0x08
    CLEAN_ALL_DATA = 0x10


class Role(db.Model):
    __tablename__ = 'role'

    id = db.Column(mysql.TINYINT, primary_key=True)
    name = db.Column(db.String(16), nullable=False)
    permission = db.Column(db.Integer, nullable=False)

    roles = OrderedDict(
        guest=Permission.READ_DATA,
        admin=Permission.READ_DATA\
              | Permission.UP_POINT | Permission.DOWN_POINT\
              | Permission.CLEAN_WAGER | Permission.CLEAN_ALL_DATA
    )

    @classmethod
    def load(cls):
        for role_name, perm in cls.roles.items():
            role = cls.query.filter(cls.name == role_name).first()
            if role is None:
                role = cls(name=role_name, permission=perm)
                db.session.add(role)
                db.session.commit()

    def __repr__(self):
        return '<{}: {}>'.format(self.name, hex(self.permission))


class User(UserMixin, db.Model):
    __tablename__ = 'user'

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(128), unique=True, index=True)
    password_hash = db.Column(db.String(128))
    status = db.Column(db.Integer, nullable=False, default=1)
    create_time = db.Column(db.Integer, nullable=False, default=ts_func)

    role_id = db.Column(mysql.TINYINT, db.ForeignKey('role.id'), nullable=False, default=1)
    role = db.relationship(
        'Role',
        backref=db.backref('users', lazy='joined')
    )

    @property
    def password(self):
        raise AttributeError('Not readable')

    @password.setter
    def password(self, value):
        self.password_hash = generate_password_hash(value)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

    @property
    def is_admin(self):
        return self.role_id == 2


@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))